package com.hhu.wangzb.shiro.filter;

import com.hhu.wangzb.common.security.AuthenticationInfo;
import com.hhu.wangzb.common.security.constant.SecurityConstants;
import com.hhu.wangzb.shiro.jwt.util.JwtUtils;
import com.hhu.wangzb.shiro.util.AuthenticationUtils;
import org.apache.shiro.web.filter.AccessControlFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * shiro结合jwt实现认证
 * shiro过滤器
 */
public class JwtFilter extends AccessControlFilter {


    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // header传递的authentication token
        String token = httpServletRequest.getHeader("authentication");

        if (token == null) return false;

        // 判断subject中是否留存登录信息
//        if (!AuthenticationUtils.isAuthenticated()) return false;

        // 解析token，出错则拒绝访问；同时检验登陆留存信息是否匹配
        try {
//            // 登陆留存信息是否不匹配
//            if (!isAuthenticationMatch(AuthenticationUtils.getAuthenticationInfo(), token)) return false;
            // 仅解析token，未采用cookie+session方式，后端无法留存session记录
            JwtUtils.verifyToken(token);
        } catch (Exception e) {
            // 解析出错
            return false;
        }

        return true;
    }


    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        // 未携带token访问，或token有误
        request.getRequestDispatcher("/forbidden").forward(request, response);
        return false;
    }

    /**
     * 检验登录状态是否匹配
     * @param storageInfo subject中贮存的登录信息
     * @param jwtToken token
     * @return 登录状态是否匹配
     */
    private boolean isAuthenticationMatch(AuthenticationInfo storageInfo, String jwtToken) {

        return storageInfo.getUserIdInSession().equals(JwtUtils.getInt(jwtToken, SecurityConstants.S_SESSION_USER_ID))
                && storageInfo.getUserRoleInSession().equals(JwtUtils.getString(jwtToken, SecurityConstants.S_SESSION_USER_ROLE))
                && Arrays.equals(storageInfo.getUserPermissionsInSession().toArray(), JwtUtils.getStringArr(jwtToken, SecurityConstants.S_SESSION_USER_PERMISSIONS));

    }
}
